package edu.ccut.saturn.component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import edu.ccut.saturn.component.listener.DebugComponentListener;

public class SaturnDebugThreadsManager {

	public static final String SUB_STR = "|__|";

	private static SaturnDebugThreadsManager instance = new SaturnDebugThreadsManager();

	private Map<String, IDebugThread> debugThread = new TreeMap<String, IDebugThread>();

	private Map<String, IDebugThread> overDebugThread = new TreeMap<String, IDebugThread>();

	private static final String DEBUG_THREAD_PATH = "debugThreadDetail.jsp?key=";

	private static final String DEBUG_COMPONENT_PATH = "debugComponentDetail.jsp?key=";

	private boolean isStart = false;

	private IComponentListener componentListener = null;

	public static SaturnDebugThreadsManager getInstance() {
		return instance;
	}

	public synchronized boolean isStart() {
		return this.isStart;
	}

	public synchronized void start() {
		if (!this.isStart) {
			if (this.componentListener == null) {
				this.componentListener = new DebugComponentListener();
			}
			ComponentManager.addComponentListener(this.componentListener);

			this.isStart = true;
		}
	}

	public synchronized void end() {
		if (this.isStart) {
			ComponentManager.removeComponentListener(this.componentListener);

			this.isStart = false;
		}
	}

	public Map<String, IDebugThread> getDebugThreadMap() {
		return this.debugThread;
	}

	public Map<String, IDebugThread> getOverDebugThreadMap() {
		return this.overDebugThread;
	}

	public IDebugThread getDebugThread(String key) {
		return this.debugThread.get(key);
	}

	public IDebugThread getOverDebugThread(String key) {
		return this.overDebugThread.get(key);
	}

	public void putDebugThread(IDebugThread debugThread) {
		this.debugThread.put(debugThread.getName(), debugThread);
	}

	public void putOverDebugThread(IDebugThread debugThread) {
		this.overDebugThread.put(debugThread.getName(), debugThread);
	}

	public void removeDebugThread(IDebugThread debugThread) {
		this.debugThread.remove(debugThread.getName());
	}

	public void clear() {
		this.debugThread.clear();
		this.overDebugThread.clear();
	}

	public List<Map<String, String>> getOverDebugThreadTreeList() {
		List<Map<String, String>> treeList = new ArrayList<Map<String, String>>();

		for (IDebugThread debugThread : this.overDebugThread.values()) {
			this.initalTreeList(treeList, debugThread);
		}

		return treeList;
	}

	private void initalTreeList(List<Map<String, String>> list,
			IDebugThread debugThread) {

		IDebugComponentInfo debugComponentInfo = debugThread
				.getDebugComponentInfo();

		String type = null;

		if (debugComponentInfo.hasLevelMessage(ILogger.LOGGER_LEVLE_ERROR)) {
			type = "error";

		} else if (debugComponentInfo
				.hasLevelMessage(ILogger.LOGGER_LEVLE_WARN)) {

			type = "warn";
		}
		String debugThreadName = debugThread.getName();
		list.add(this.createNode(debugThread.hashCode(), debugThreadName,
				DEBUG_THREAD_PATH + debugThreadName, -1, type));

		String debugComponentName = debugComponentInfo.getName();
		
		if (type == null) {
			type = "action";
		}
		list.add(this.createNode(debugComponentInfo.hashCode(),
				debugComponentName, DEBUG_COMPONENT_PATH + debugThreadName,
				debugThread.hashCode(), type));

		this.initalTreeList(list, debugComponentInfo, debugThreadName);
	}

	private void initalTreeList(List<Map<String, String>> list,
			IDebugComponentInfo debugComponentInfo, String parentKey) {

		List<IDebugComponentInfo> children = debugComponentInfo.getChildren();

		if (children != null && !children.isEmpty()) {
			int i = 0;

			for (IDebugComponentInfo child : children) {
				String name = child.getName();
				String type = child.getNodeInfo().getNodeType();

				if (child.hasLevelMessage(ILogger.LOGGER_LEVLE_ERROR)) {
					type = "error";

				} else if (child.hasLevelMessage(ILogger.LOGGER_LEVLE_WARN)) {
					type = "warn";
				}
				String pathKey = parentKey + SUB_STR + (i++);
				list.add(this.createNode(child.hashCode(), name,
						DEBUG_COMPONENT_PATH + pathKey, debugComponentInfo
								.hashCode(), type));

				this.initalTreeList(list, child, pathKey);
			}
		}
	}

	private Map<String, String> createNode(long id, String name, String path,
			long parentId, String type) {

		Map<String, String> node = new HashMap<String, String>();
		String image = null;

		if (type != null) {
			image = "component/" + type + ".gif";
		}
		node.put("id", id + "");
		node.put("name", name);
		node.put("path", path);
		node.put("icon", image);
		node.put("expandedIcon", image);

		if (parentId > 0 && parentId != id) {
			node.put("parentId", parentId + "");
		} else {
			node.put("parentId", "");
		}

		return node;

	}
}
